/*
 * Copyright 2011-2012 by The Regents of the University of California Licensed
 * under the Apache License, Version 2.0 (the "License"); you may not use this
 * file except in compliance with the License. you may obtain a copy of the
 * License from
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package edu.ucsd.db.bassarisk.storage.loading;

import java.nio.ByteBuffer;

import edu.ucsd.db.bassarisk.data.values.IntType.IntTools;
import edu.ucsd.db.bassarisk.data.values.IntType.IntegerValueCodec;
import edu.ucsd.db.bassarisk.storage.common.ColumnStore;

public abstract class FixedLengthAscendingIntegerSegmentIndexer implements
    IColumnSegmentIndexer {

  protected static final IntegerValueCodec intManip = IntTools.INSTANCE
      .getGenericCodec();

  protected int[] segmentMinValues;
  protected int[] segmentValueCounts;

  protected int numIndexedSegments;

  @Override
  public int cardsRequired() {
    int indexSize = this.numIndexedSegments * this.getBytesPerEntry();
    int headerSize = this.getBytesForHeader();

    float totalBytes = indexSize + headerSize;
    int cards = (int) Math.ceil(totalBytes / ColumnStore.BYTES_IN_CARD);
    return cards;
  }

  protected abstract int getBytesForHeader();

  protected abstract int getBytesPerEntry();

  @Override
  public void reset() {
    this.numIndexedSegments = 0;
  }

  protected abstract void writeHeaderValues(ByteBuffer drawer, int headerEndOffset);

  @Override
  public int writeIndex(final ByteBuffer drawer, final int startCardIndex) {
    int cardsRequired = this.cardsRequired();
    int lastCardIndex = startCardIndex + cardsRequired - 1;
    assert lastCardIndex < ColumnStore.CARDS_IN_DRAWER;

    int headerEndOffset = (lastCardIndex + 1) * ColumnStore.BYTES_IN_CARD;
    int spaceRequired = cardsRequired * ColumnStore.BYTES_IN_CARD;
    drawer.position(ColumnStore.BYTES_IN_DRAWER - spaceRequired);

    int i = 0;
    for (; i < this.numIndexedSegments; ++i) {
      drawer.putInt(this.segmentMinValues[i]);
    }

    this.writeHeaderValues(drawer, headerEndOffset);
    return cardsRequired;
  }

}
